package com.sjgl.esdn.controller;

import com.sjgl.esdn.domain.AjaxResultESDN;
import com.sjgl.esdn.domain.entity.TempBlog;
import com.sjgl.esdn.domain.entity.vo.UploadBlogVo;
import com.sjgl.esdn.service.DeptService;
import com.sjgl.esdn.service.FileService;
import com.sjgl.esdn.utils.DateUtilsESDN;
import com.sjgl.esdn.utils.ImageUtilsESDN;
import com.sjgl.esdn.utils.OpenOfficeUtils;
import com.sjgl.esdn.utils.Word2PdfESDN;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 文件 控制层
 *
 * @author 缪恒铭
 * @date 2022/08/05
 */
@RestController
@RequestMapping("/file")
public class FileController extends BaseControllerESDN {
    @Resource
    private RestHighLevelClient esclient;

    private static final String ESDN_INDEX = "esdn2";
    @Autowired
    FileService fileService;

    @Autowired
    DeptService deptService;

    /**
     * 上传博客
     *
     * @param blog 博客
     * @return {@code AjaxResultESDN}
     */
    @PostMapping("/uploadBlog")
    public AjaxResultESDN uploadBlog(MultipartFile fileCover,UploadBlogVo blog){
//        System.out.println(blog);//测试

        //构造数据
        com.sjgl.esdn.domain.entity.File file=new com.sjgl.esdn.domain.entity.File();
        file.setCreateBy(blog.getUserId());
        file.setFileName(blog.getFileName());
        file.setFileType(blog.getFileType());
        file.setFileIntro(blog.getFileIntro());
        file.setColumnId(blog.getColumnId());
        file.setTempBlogId(blog.getTempBlogId());
        file.setFileSuffix("rtf");
        file.setIsBlog(1);

        //数据库处理
        List<Long> deptIdList = deptService.getIdListByDeptNameList(blog.getDeptNameList());
        if (fileService.insertFile(file, deptIdList ,blog.getLabelIdList()) == 0) {
            return AjaxResultESDN.error("博客" + file.getFileName() + "上传失败" + ",数据库出错");
        }
        file=fileService.selectFileById(file.getFileId());

        //获得文件路径
        String path = fileService.selectFilePathById(file.getFileId());
        File t = new File(path);
        if (!t.getParentFile().exists()) {
            t.getParentFile().mkdirs();
        }

        //文件保存
        try(FileWriter fw = new FileWriter(t)) {
            fw.write(blog.getContent());
        } catch (IOException e) {
            return AjaxResultESDN.error("博客" + file.getFileName() + "上传失败" + ",IO异常");
        }

        //若有上传预览图，则保存
        String previewPath = fileService.selectFolder("preview") + DateUtilsESDN.getYYYYMMByDate(file.getCreateTime()) + "\\" + file.getFileId() + ".jpg";
        if(fileCover!=null){
            try {
                fileCover.transferTo(new File(previewPath));
            } catch (IOException e) {
                return AjaxResultESDN.error("预览图" + fileCover.getOriginalFilename() + "上传失败" + ",IO异常");
            }
        }

        //文件保存完毕，操作es
        try {
            fileService.insertFileES(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return AjaxResultESDN.success("博客" + blog.getFileName() + "上传成功").put("fileId", file.getFileId());
    }

    /**
     * 保存临时博客
     *
     * @param tempBlog 临时博客
     * @return {@code AjaxResultESDN}
     */
    @PostMapping("/saveTempBlog")
    public AjaxResultESDN saveTempBlog(@RequestBody TempBlog tempBlog){
        fileService.saveTempBlog(tempBlog);
        return AjaxResultESDN.success();
    }

    /**
     * 获得临时博客列表
     *
     * @return {@code AjaxResultESDN}
     */
    @GetMapping("/tempBlogList")
    public AjaxResultESDN getTempBlogList(@RequestParam Long userId){
        return AjaxResultESDN.success(fileService.getTempBlogList(userId));
    }

    /**
     * 上传文件
     *
     * @param uploadFile 上传文件
     * @param file       文件(文件类型，文件简介（可选）)
     * @param fileCover
     * @return {@code AjaxResultESDN}
     */
    @PostMapping("/upload")
    public AjaxResultESDN uploadFile(MultipartFile uploadFile, MultipartFile fileCover, com.sjgl.esdn.domain.entity.File file) {

        //获得标题、后缀
        String name = uploadFile.getOriginalFilename();
        int splitPoint = fileService.getSplitPoint(name);
        if (splitPoint == -1) {
            return AjaxResultESDN.error("文件" + uploadFile.getOriginalFilename() + "无后缀");
        }
        file.setFileName(name.substring(0, splitPoint));
        file.setFileSuffix(name.substring(splitPoint + 1));

        //数据库处理
        if (fileService.selectFolder(file.getFileSuffix())==null) {
            return AjaxResultESDN.error("文件" + uploadFile.getOriginalFilename() + "后缀不支持");
        }
        file.setCreateBy(file.getUserId());
        List<Long> deptIdList = deptService.getIdListByDeptNameList(file.getDeptNameList());
        if (fileService.insertFile(file, deptIdList ,file.getLabelIdList()) == 0) {
            return AjaxResultESDN.error("文件" + uploadFile.getOriginalFilename() + "上传失败" + ",数据库出错");
        }
        file=fileService.selectFileById(file.getFileId());

        //获得文件路径
        String path = fileService.selectFilePathById(file.getFileId());
        File t = new File(path);
        if (!t.getParentFile().exists()) {
            t.getParentFile().mkdirs();
        }

        //文件保存
        try {
            uploadFile.transferTo(t);
        } catch (IOException e) {
            return AjaxResultESDN.error("文件" + uploadFile.getOriginalFilename() + "上传失败" + ",IO异常");
        }

        //若文件可转pdf，再保存一份pdf版本
        String pdfPath = fileService.selectPdfPathById(file.getFileId());
        if (fileService.canFileToPdf(file.getFileSuffix())) {
            File file1=new File(pdfPath);
            if (!file1.getParentFile().exists()) {
                file1.getParentFile().mkdirs();
            }
            OpenOfficeUtils.convertToPdf(path, pdfPath);
        }

        //获得预览图地址
        String previewPath = fileService.selectFolder("preview") + DateUtilsESDN.getYYYYMMByDate(file.getCreateTime()) + "\\" + file.getFileId() + ".jpg";
        File file2=new File(previewPath);
        if (!file2.getParentFile().exists()) {
            file2.getParentFile().mkdirs();
        }

        //若有上传预览图，则保存；否则若文件有pdf版本，对首页截图保存
        if(fileCover!=null){
            try {
                fileCover.transferTo(file2);
            } catch (IOException e) {
                return AjaxResultESDN.error("预览图" + fileCover.getOriginalFilename() + "上传失败" + ",IO异常");
            }
        }else if (new File(pdfPath).exists()) {
            Word2PdfESDN.pdf2preview(pdfPath, previewPath);
        }

        //文件保存完毕，操作es
        try {
            fileService.insertFileES(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        return AjaxResultESDN.success("文件" + uploadFile.getOriginalFilename() + "上传成功").put("fileId", file.getFileId());
    }

    /**
     * 上传多文件
     *
     * @param uploadFile   上传文件
     * @param userId       用户id
     * @param file         文件
     * @param deptNameList 部门名字列表
     * @return {@link AjaxResultESDN}
     */
//    @PostMapping("/uploads")
//    public AjaxResultESDN uploadFiles(List<MultipartFile> uploadFile, Long userId, com.sjgl.esdn.domain.entity.File file, @Nullable @RequestParam("deptNameList") List<String> deptNameList) {
//        List<AjaxResultESDN> list = new ArrayList<>();
//
//        for (MultipartFile multipartFile : uploadFile) {
//            list.add(uploadFile(multipartFile, userId, file, deptNameList));
//        }
//        AjaxResultESDN ajax = AjaxResultESDN.success("上传成功");
//        for (AjaxResultESDN ajaxResult : list) {
//            if ((Integer) (ajaxResult.get(AjaxResultESDN.CODE_TAG)) != 200) {
//                ajax = AjaxResultESDN.error("有文件上传异常");
//                break;
//            }
//        }
//        ajax.put(AjaxResultESDN.DATA_TAG, list);
//        return ajax;
//    }

    /**
     * 更新文件
     *
     * @param file 文件
     * @return {@link AjaxResultESDN}
     */
    @PutMapping("/update")
    public AjaxResultESDN updateFile(@RequestBody com.sjgl.esdn.domain.entity.File file) {
        file.setUpdateBy(file.getUserId());
        List<Long> deptIdList = deptService.getIdListByDeptNameList(file.getDeptNameList());
        int result = fileService.updateFile(file, deptIdList);
        if (result == -1) {
            return AjaxResultESDN.error("参数出错");
        } else if (result == 0) {
            return AjaxResultESDN.error("用户无权限");
        }


        return AjaxResultESDN.success("修改成功");
    }

    /**
     * 删除文件（伪删）
     *
     * @param fileId 文件id
     * @param userId 用户id
     * @param reason 原因（可选）
     * @return {@link AjaxResultESDN}
     */
    @DeleteMapping("/delete")
    public AjaxResultESDN deleteFile(Long fileId, Long userId, String reason) {
        int result = fileService.deleteFile(fileId, userId, reason);
        if (result == -1) {
            return AjaxResultESDN.error("参数错误，文件id或用户id出错");
        }
        if (result == 0) {
            return AjaxResultESDN.error("删除失败，用户无权限");
        }
        return AjaxResultESDN.success("删除成功");
    }

    /**
     * 下载文件
     *
     * @param userId   用户id
     * @param fileId   文件id
     * @param response 响应
     * @return {@link AjaxResultESDN}
     * @throws IOException ioexception
     */
    @GetMapping("/download")
    public void downloadFile(Long userId, Long fileId, @RequestParam(defaultValue = "false", required = false) Boolean toPdf, HttpServletResponse response) throws IOException {
        //数据库处理
        int result = fileService.downloadFile(fileId, userId);
        if (result == -1) {
            return;
//            return AjaxResult.error("参数错误，文件id或用户id出错");
        }
        if (result == 0) {
            return;
//            return AjaxResult.error("请求失败，用户无权限");
        }

        //获得完整路径和原始文件名
        com.sjgl.esdn.domain.entity.File file = fileService.selectFileById(fileId);
        String filename;
        String path;
        if (toPdf) {
            filename = file.getFileName() + ".pdf";
            path = fileService.selectPdfPathById(fileId);
            if (!new File(path).exists()) {
                return;
//                return AjaxResult.error("该类型文件不支持转pdf");
            }
        } else {
            filename = file.getFileName() + "." + file.getFileSuffix();
            path = fileService.selectFilePathById(fileId);
            if (!new File(path).exists()) {
                return;
//                return AjaxResult.error("文件已失效");
            }
        }


        //返回数据
        InputStream inputStream = new FileInputStream(path);
//        response.reset();
//        response.setContentType("application/octet-stream; charset=UTF-8");
        response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
        ServletOutputStream outputStream = response.getOutputStream();
        byte[] b = new byte[1024];
        int len;
        //从输入流中读取一定数量的字节，并将其存储在缓冲区字节数组中，读到末尾返回-1
        while ((len = inputStream.read(b)) > 0) {
            outputStream.write(b, 0, len);
        }
        inputStream.close();

        //修改es下载量数据

//        return AjaxResult.success("请求成功");
    }

    /**
     * 文件预览图
     *
     * @param fileId 文件id
     * @return {@link ResponseEntity}<{@link byte[]}>
     * @throws Exception 异常
     */
    @GetMapping(value = "/preview/{fileId}")
    public String previewFile(@PathVariable("fileId") Long fileId) throws Exception {
        return ImageUtilsESDN.fileToBase64(fileService.selectPreviewPath(fileId));
    }

    /**
     * 文件浏览
     *
     * @param fileId 文件id
     * @return {@link AjaxResultESDN}
     * @throws IOException ioexception
     */
    @GetMapping("/look")
    public AjaxResultESDN getFile(@RequestParam("fileId") Long fileId, @RequestParam("userId") Long userId) throws IOException {
        if (!fileService.isFileExist(fileId)) {
            return AjaxResultESDN.error("文件不存在或已失效");
        }

        if(!fileService.canUserLookFile(userId,fileId)){
            return AjaxResultESDN.error("用户无权限查看该文件");
        }

        return AjaxResultESDN.success(fileService.lookFile(fileId, userId));
    }

    /**
     * 变热文件列表
     *
     * @param userId 用户id
     * @return {@code AjaxResultESDN}
     * @throws IOException ioexception
     */
    @GetMapping("/hotFileList")
    public AjaxResultESDN getHotFileList(@RequestParam("userId") Long userId) throws IOException {

        return AjaxResultESDN.success(fileService.getHotFileList(userId,15L));
    }

    @GetMapping("/downloadFileList")
    public AjaxResultESDN getDownloadFileList(@RequestParam("userId") Long userId,@RequestParam("days") Long days) throws IOException {

        return AjaxResultESDN.success(fileService.getRecentDownloadFileList(userId,days,9L));
    }
}
